package com.zengdada.authority.service.impl;

import com.github.pagehelper.PageInfo;
import com.zengdada.authority.model.DmlColumn;
import com.zengdada.authority.model.DynamicTable;
import com.zengdada.authority.model.DynamicTableColumn;
import com.zengdada.authority.model.DynamicTableColumnSearch;
import com.zengdada.authority.service.*;
import com.zengdada.authority.utils.CommonUtils;
import com.zengdada.authority.utils.mapper.Sort;
import com.zengdada.authority.utils.where.Where;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.Fn;
import tk.mybatis.mapper.weekend.WeekendSqls;
import tk.mybatis.mapper.weekend.reflection.Reflections;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: 12614
 * @Contact: 1261438511@qq.com
 * @Date: 2019/3/7 11:06
 * @Description:
 */
@Service
public class DynamicTableColumnAuthorityServiceImpl extends EnhanceBaseService<DynamicTableColumn> implements DynamicTableColumnAuthorityService {

    @Autowired
    @Qualifier("dmlColumnAuthorityServiceImpl")
    DmlColumnAuthorityService dmlColumnAuthorityService;
    @Autowired
    @Qualifier("dynamicTableAuthorityServiceImpl")
    DynamicTableAuthorityService dynamicTableAuthorityService;

    @Autowired
    @Qualifier("dynamicTableColumnSearchAuthorityServiceImpl")
    DynamicTableColumnSearchAuthorityService dynamicTableColumnSearchAuthorityService;

    @Override
    public void save(DynamicTableColumn dynamicTableColumn, DynamicTableColumnSearch search) {
        search.setDataType(formatClass(search.getDataType()));
        if (StringUtils.isBlank(dynamicTableColumn.getDmlColumnId())) dynamicTableColumn.setDisSort("false");
        if (StringUtils.isBlank(dynamicTableColumn.getId())) {// 添加
            try {
                CommonUtils.reflectObjectTransString(dynamicTableColumn, false);
                CommonUtils.reflectObjectTransString(search, false);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
            this.add(dynamicTableColumn);
            search.setId(dynamicTableColumn.getId());
            dynamicTableColumnSearchAuthorityService.add(search);
        } else {
            try {
                CommonUtils.reflectObjectTransString(dynamicTableColumn, true);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
            this.updateById(dynamicTableColumn);
            if (dynamicTableColumnSearchAuthorityService.selectById(search.getId()) == null) {
                try {
                    CommonUtils.reflectObjectTransString(search, false);
                } catch (Exception e) {
                    throw new RuntimeException(e.getMessage());
                }
                search.setId(dynamicTableColumn.getId());
                dynamicTableColumnSearchAuthorityService.add(search);
            } else
                dynamicTableColumnSearchAuthorityService.updateById(search);
        } //修改

    }

    private String formatClass(String classReference) {
        Class<?> outClass = null;
        try {
            Class<?> inClass = Class.forName(classReference);
            if (classInstanceof(inClass, Date.class))
                outClass = Date.class;
            else if (classInstanceof(inClass, Integer.class))
                outClass = Integer.class;
            else if (classInstanceof(inClass, Long.class))
                outClass = Long.class;
            else if (classInstanceof(inClass, BigDecimal.class))
                outClass = BigDecimal.class;
            else if (classInstanceof(inClass, Short.class) || classInstanceof(inClass, Float.class) || classInstanceof(inClass, Double.class))
                outClass = BigDecimal.class;
            else
                outClass = String.class;
        } catch (Exception e) {
            e.printStackTrace();
        }

        Class<?> finalOutClass = outClass;
        Where.FieldType javaType = null;
        try {
            javaType = CommonUtils.enumValueOf(Where.FieldType.class, new HashMap<String, Object>() {{
                put("javaType", finalOutClass);
            }});
        } catch (Exception e) {
            e.printStackTrace();
        }
        return javaType == null ? null : javaType.getName();
    }

    private boolean classInstanceof(Class<?> current, Class<?> target) {
        if (current == null) return false;
        return current.equals(target) || classInstanceof(current.getSuperclass(), target);
    }

    @Override
    public int batchDelete(String id) {
        if (StringUtils.isBlank(id)) return 0;
        return mapper.deleteByExample(new Example.Builder(DynamicTableColumn.class).where(WeekendSqls.<DynamicTableColumn>custom().andIn(DynamicTableColumn::getId, Arrays.stream(id.split(",")).collect(Collectors.toList()))).build());
    }

    @Override
    public void autoGenerationColumn(String dynamicTableId, boolean b) {
        DynamicTable dynamicTable = dynamicTableAuthorityService.selectById(dynamicTableId);
        if (dynamicTable == null)
            throw new RuntimeException(String.format("没有找到 dynamicTableId 为 %s 的数据", dynamicTableId));
        if (b) // 如果是强制重新生成 删除绑定的数据列
            mapper.deleteByExample(new Example.Builder(DynamicTableColumn.class)
                    .where(WeekendSqls.<DynamicTableColumn>custom().andEqualTo(DynamicTableColumn::getDynamicTableId, dynamicTableId).andIsNotNull(DynamicTableColumn::getDmlColumnId)).build());
        PageInfo<DmlColumn> dmlColumnPageInfo = dmlColumnAuthorityService.selectPageInfoByParam(new Where(Where.Formula.AND,Arrays.asList(new Where("dmlId", dynamicTable.getDmlId()), new Where("isValid", "1", Where.FieldType.NUMBER))), null, new Sort("columnIndex"));
        List<DmlColumn> dmlColumns = dmlColumnPageInfo.getList().stream().filter(i -> (i.getAttrs() & 32) == 32 && ((i.getAttrs() & 512) == 512 || (i.getAttrs() & 256) == 256)).collect(Collectors.toList());
        if (dmlColumns.size() == 0) {
            throw new RuntimeException("没有可生成的字段，请在dml字段中设置需要显示的字段属性为 可查询 并且 可显示 ");
        }
        List<DynamicTableColumn> dynamicTableColumns = mapper.selectByExample(new Example.Builder(DynamicTableColumn.class)
                .select(Reflections.fnToFieldName((Fn<DynamicTableColumn, Object>) DynamicTableColumn::getId), Reflections.fnToFieldName((Fn<DynamicTableColumn, Object>) DynamicTableColumn::getDmlColumnId))
                .where(WeekendSqls.<DynamicTableColumn>custom().andEqualTo(DynamicTableColumn::getDynamicTableId, dynamicTableId)).build());
        DynamicTableColumn column;
        for (DmlColumn dmlColumn : dmlColumns) {
            try {
                column = dynamicTableColumns.stream().filter(e -> dmlColumn.getId().equals(e.getDmlColumnId())).collect(Collectors.toList()).get(0);
                column.setDisSort(String.valueOf((dmlColumn.getAttrs() & 512) == 512 && (dmlColumn.getAttrs() & 64) == 64));
                if ((dmlColumn.getAttrs() & 512) != 512)
                    column.setSort(0);
                column.setState(1);
                mapper.updateByPrimaryKeySelective(column);
            } catch (Exception e) { // 表示原来没有
                column = new DynamicTableColumn();
                column.setType("normal");
                column.setDynamicTableId(dynamicTableId);
                column.setSort((dmlColumn.getAttrs() & 512) == 512 ? dmlColumn.getColumnIndex() : 0);
                column.setDmlColumnId(dmlColumn.getId());
                column.setTitle(StringUtils.isBlank(dmlColumn.getCaption()) ? dmlColumn.getLabel() : dmlColumn.getCaption());
                column.setDisSort(String.valueOf((dmlColumn.getAttrs() & 512) == 512 && (dmlColumn.getAttrs() & 64) == 64));
                mapper.insertSelective(column);
            }
        }
    }

    @Override
    public Map<String, Object> selectDetailedAndSearchById(String id) {
        Map<String, Object> map = this.selectDetailedById(id);
        Map<String, Object> search = dynamicTableColumnSearchAuthorityService.selectDetailedById(id);
        if (search != null) search.forEach((k, v) -> {
            map.put("search." + k, v);
        });
        return map;
    }
}
